package com.dz51.core.proxy;

import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate3.HibernateTemplate;

public class MasterTemplateContainer extends AbstractTemplateContainer {
	private Logger logger = Logger.getLogger(MasterTemplateContainer.class);

	// @Autowired
	// private SlaveTemplateContainer slaveTemplateContainer;

	@Override
	public DataSourceType getDataSourceType() {
		return DataSourceType.MASTER;
	}

	@Override
	public void changDataSource(HibernateTemplate hibernateTemplate, boolean add) {
		// TODO 更改数据源 供check调用
		synchronized (MasterTemplateContainer.class) {
			try {
				if (!add) {
					hdaoTemplateIndex.set(-1);
					String subject = "强烈警告：Mysql数据库 master 错误次数太多，被移除，写服务已暂停！";
					String content = "强烈警告：Mysql数据库 master 错误次数太多，被移除，写服务已暂停！ 当前master容器还包含 " + hibernateTemplates.size() + " 个数据源";
					sendWarnNotice(subject, content);
				} else {
					logger.info("检测正常，什么都不做");
				}

				logger.info("master 切换数据源");
			} catch (Exception e) {
				logger.error("master 切换数据源发生异常", e);

				String msg = e.getMessage();
				sendWarnNotice("master 切换数据源发生异常", msg);
			}
		}
	}

	@Override
	public void changDataSource(JdbcTemplate jdao, boolean add) {
		// TODO 更改数据源 供check调用
		synchronized (MasterTemplateContainer.class) {
			try {
				if (!add) {// 移除
					hdaoTemplateIndex.set(-1);
					String subject = "强烈警告：Mysql数据库 master 错误次数太多，被移除，写服务已暂停！";
					String content = "强烈警告：Mysql数据库 master 错误次数太多，被移除。写服务已暂停！ 当前master容器还包含 " + jdbcTemplates.size() + " 个数据源";
					content += extractDBInfo(jdao);
					sendWarnNotice(subject, content);
				} else {
					logger.info("检测正常，什么都不做");
				}
				logger.info("master 切换数据源");
			} catch (Exception e) {

				logger.error("master 切换数据源发生异常", e);
				String msg = e.getMessage();
				sendWarnNotice("master 切换数据源发生异常", msg);
			}
			// 切换master!!!! change master
		}
	}

	@Override
	public int hash(TemplateType templateType) {
		if (hdaoTemplateIndex.get() == -1)
			return -1;
		if (TemplateType.HibernageTemplate.equals(templateType)) {
			int result = hdaoTemplateIndex.get() % hdaoSize.get();
			// logger.info("master采用数据源" + result);
			return result;
		} else if (TemplateType.JdbcTemplate.equals(templateType)) {
			int result = jdaoTemplateIndex.get() % jdaoSize.get();
			// logger.info("master采用数据源" + result);
			return result;
		} else
			return -1;
	}

	@Override
	public void check() {
		// TODO master的检测程序
		logger.info("启动master检测程序");
		for (final JdbcTemplate jdao : jdbcTemplates) {
			threadPoolExecutor.execute(new Runnable() {
				@Override
				public void run() {
					checkMaster(jdao);
				}
			});
		}

		for (final HibernateTemplate hdao : hibernateTemplates) {
			threadPoolExecutor.execute(new Runnable() {
				@Override
				public void run() {
					checkMaster(hdao);
				}
			});
		}
	}

	/** jdbctemplate检测master状态 **/
	private void checkMaster(JdbcTemplate jdao) {
		int loopErrors = errorTimes;
		int loopSuccess = successTimes;
		while (true) {
			boolean success = true;
			try {
				if (jdao == null) {
					success = false;
					continue;
				}
				success = checkMasterStatusOnce(jdao);
			} catch (Exception e1) {
				logger.error("", e1);
				success = false;
			}
			if (success) {
				loopSuccess--;
				loopErrors = errorTimes;
			} else {
				loopErrors--;
				loopSuccess = successTimes;
			}
			if (loopErrors <= 0) {
				logger.info("master检测" + errorTimes + "次错误，开始切换数据源");
				changDataSource(jdao, false);// 移除
				loopErrors = errorTimes;
				loopSuccess = successTimes;
			}
			// if(loopSuccess <= 0 && templateIndex.get() != 0){
			// logger.info("master检测5次正常，开始切换数据源");
			// changDataSource(jdao, true);//添加
			// loopErrors = errorTimes;
			// loopSuccess = successTimes;
			// }
			// 休眠一秒
			try {
				Thread.sleep(checkInterval);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	/** jdbctemplate检测master状态 **/
	private void checkMaster(HibernateTemplate hdao) {
		int loopErrors = errorTimes;
		int loopSuccess = successTimes;
		while (true) {
			boolean success = true;
			try {
				if (hdao == null) {
					success = false;
					continue;
				}
				success = checkMasterStatusOnce(hdao);
			} catch (Exception e1) {
				logger.error("", e1);
				success = false;
			}
			if (success) {
				loopSuccess--;
				loopErrors = errorTimes;
			} else {
				loopErrors--;
				loopSuccess = successTimes;
			}
			if (loopErrors <= 0) {
				logger.info("master检测" + errorTimes + "次错误，开始切换数据源");
				changDataSource(hdao, false);// 移除
				loopErrors = errorTimes;
				loopSuccess = successTimes;
			}
			// 休眠一秒
			try {
				Thread.sleep(checkInterval);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public boolean init() throws Exception {
		logger.info("[ Master 容器初始化开始 ]");
		boolean success = super.init(true);
		logger.info("Master 初始化了  " + hibernateTemplates.size() + " 个hibernateTemplates数据源");
		logger.info("Master 初始化了  " + jdbcTemplates.size() + " 个jdbcTemplates数据源");
		logger.info("[ Master 容器初始化完毕 ]");
		return success;
	}
}
